﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.IO;
using System.Windows.Forms;

namespace Anyask
{
    public class NetMessageEventArgs : EventArgs
    {
        private string message;
        public NetMessageEventArgs(string s)
        {
            message = s;
        }

        public string Message
        {
            get { return message; }
            set { message = value; }
        }

    }

    // thread safe singletone
    public class net
    {
        //public delegate void DataRecieveHandler(object sender, string str);
        public event EventHandler<NetMessageEventArgs> RaiseDataReceivedEvent;
        static readonly object padlock = new object();

        static net instance = null;
        public static net Instance
        {
            get
            {
                lock (padlock)
                {
                    if (instance == null)
                    {
                        instance = new net();
                    }
                    return instance;
                }
            }
        }

        private Socket socket = null;
        private AsyncCallback socketCallback;
        private IAsyncResult result;

        //public delegate void DataReceivedHandler(object sender, EventArgs e);
        //public event DataReceivedHandler OnDataReceived;

        //NetworkStream nsStream = null;
        //StreamWriter swWriter = null;

        public net()
        {
            try
            {
                socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                string ip = "localhost"; //"weekdo.com";
                socket.Connect(ip, 1337);
                if (socket.Connected)
                {
                    waitForData();
                }
            }
            catch (SocketException se)
            {
                MessageBox.Show("\nConnection failed, is the server running?\n" + se.Message);
            }

            //tcpClient = new TcpClient("127.0.0.1", 1337);
            //nsStream = tcpClient.GetStream();
            //swWriter = new StreamWriter(nsStream);
        }

        ~net()
        {
            //swWriter.Close();
            //nsStream.Close();
        }

        public void send(string msg)
        {
            try
            {
                // New code to send strings
                NetworkStream networkStream = new NetworkStream(socket);
                System.IO.StreamWriter streamWriter = new System.IO.StreamWriter(networkStream);
                streamWriter.WriteLine(msg);
                streamWriter.Flush();

                /* Use the following code to send bytes
                byte[] byData = System.Text.Encoding.ASCII.GetBytes(objData.Tostring ());
                if(m_clientSocket != null){
                    m_clientSocket.Send (byData);
                }
                */
            }
            catch (SocketException se)
            {
                MessageBox.Show(se.Message);
            }
            /*if (tcpClient.Connected)
            {
                swWriter.WriteLine(bytes);
                swWriter.Flush();
            }*/
        }

        private void waitForData()
        {
            try
            {
                if (socketCallback == null)
                {
                    socketCallback = new AsyncCallback(DataRecievedCallback);
                }
                SocketPacket theSocPkt = new SocketPacket();
                theSocPkt.thisSocket = socket;

                // Start listening to the data asynchronously
                result = socket.BeginReceive(theSocPkt.dataBuffer,
                                                0, theSocPkt.dataBuffer.Length,
                                                SocketFlags.None,
                                                socketCallback,
                                                theSocPkt);
            }
            catch (SocketException se)
            {
                MessageBox.Show(se.Message);
            }

        }

        public class SocketPacket
        {
            public System.Net.Sockets.Socket thisSocket;
            public byte[] dataBuffer = new byte[1024];
        }

        private void DataRecievedCallback(IAsyncResult asyn)
        {
            try
            {
                SocketPacket theSockId = (SocketPacket)asyn.AsyncState;
                int iRx = theSockId.thisSocket.EndReceive(asyn);
                char[] chars = new char[iRx + 1];
                System.Text.Decoder d = System.Text.Encoding.UTF8.GetDecoder();
                int charLen = d.GetChars(theSockId.dataBuffer, 0, iRx, chars, 0);
                string szData = new string(chars);

                OnRaiseDataReceivedEvent(new NetMessageEventArgs(szData));

                /*if (DataReceived != null)
                {
                    DataReceived(this, szData);   //抛出事件，给所有响应者
                }*/

                //MessageBox.Show("hahah = " + szData);
                //room.recieveCallback(szData);

                waitForData();
            }
            catch (ObjectDisposedException)
            {
                System.Diagnostics.Debugger.Log(0, "1", "\nOnDataReceived: Socket has been closed\n");
            }
            catch (SocketException se)
            {
                MessageBox.Show(se.Message);
            }
        }


        protected virtual void OnRaiseDataReceivedEvent(NetMessageEventArgs e)
        {
            EventHandler<NetMessageEventArgs> handler = RaiseDataReceivedEvent;

            if (handler != null)
            {
                handler(this, e);
            }
        }

    }
}
